package com.atguigu.gulimall.search.thread;

import java.util.concurrent.*;

public class ThreadTest {
    /**
     * 1、继承Thread
     *         Thread01 thread = new Thread01();
     *         thread.start();
     * 2、实现Runnable接口
     *         Runnable01 runnable01 = new Runnable01();
     *         Thread thread = new Thread(runnable01);
     *         thread.start();
     * 3、实现Callable接口 + FutureTask (可以拿到返回结果，可以处理异常)
     *         FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
     *         new Thread(futureTask).start();
     *         //调用get则会阻塞，因为需要获取结果
     *         Integer i = futureTask.get();
     * 4、线程池
     *         给线程池直接提交任务
     *             第一种：
     *             public static ExecutorService executorService = Executors.newFixedThreadPool(10);
     *             executorService.execute(new Runnable01());
     * 区别：
     *     1、2不能得到返回值  3可以得到返回值
     *     1、2、3都不能控制资源
     *     4可以控制资源,性能稳定。
     */
    //我们以后在业务代码里面，以上三种启动线程的方式都不用，用线程池
    /**
     * 先创建core数量的线程数
     * 随着任务增加core如果用完了，那就任务加进Queue
     * Queue满了就新增线程，但总数不能超过max
     * 如果最终超过max那就handler处理
     * <p>
     * 如果有存在线程空闲时间超过KeepAliveTime那么则销毁
     */
    /*
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
            10,
            20,
            1000,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(500),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());
    //Executors.newCachedThreadPool(); //core为0 所有都可以回收
    //Executors.newFixedThreadPool(10);//core==max 固定数量的
    //Executors.newScheduledThreadPool();//定时任务的线程池
    //Executors.newSingleThreadExecutor();//单一一个线程池
    */
    public static ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        System.out.println("main...start....");
        /*
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }, executorService);
         */
        /*
        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executorService);
        System.out.println(integerCompletableFuture.get());
        System.out.println("main...end...");
         */
        /**
         * 稍微总结一下
         * runAsync无法获得返回结果
         * supplyAsync可以获得返回结果
         * whenComplete可以用来获取返回结果和异常
         * exceptionally可以用来修改返回值和感知异常
         * 方法完成后的感知：如果成功无法修改res
         */
        /*
        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果：" + i);
            return i;
        }, executorService).whenComplete((res, exc) -> {
            //可以感知异常，但是没法修改返回数据
            System.out.println("异步任务成功完成了...结果是:" + res + ";异常是:" + exc);
        }).exceptionally(
            //可以感知异常，同时返回默认值
            throwable -> {
                return 10;
            }
        );
        Integer integer = integerCompletableFuture.get();
        System.out.println("main...end...result:" + integer);
         */

        /**
         * 方法执行完后的处理，handle比较完善，可以修改res和感知exc
         */
        /*
        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executorService).handle((res,exc)->{
            if(res!=null){
                return res*2;
            }
            if(exc!=null){
                return 0;
            }
            return 0;
        });
        //R apply(T t, U u);
        Integer integer = integerCompletableFuture.get();
        System.out.println("main...end...result:" + integer);
         */
        /**
         * 线程串行化
         * thenRun无法获得上一步的执行结果
         * thenAccept可以
         * thenApply获取并返回
         */
        /*
        CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果：" + i);
            return i;
        }, executorService).thenRunAsync(()->{
            System.out.println("当前线程：" + Thread.currentThread().getId());
            System.out.println("任务2启动了");
        },executorService);
        */
        /*
        CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果：" + i);
            return i;
        }, executorService).thenAcceptAsync((res) -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            System.out.println("任务2启动了,上一步结果：" + res);
        }, executorService);
         */
        /*
        CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果：" + i);
            return i;
        }, executorService).thenApplyAsync((res) -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            System.out.println("任务2启动了,上一步结果：" + res);
            return res * 2;
        }, executorService);
         */

        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果1：" + i);
            return i;
        }, executorService);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2：" + Thread.currentThread().getId());
            System.out.println("运行结果2：");
            return "Hello";
        }, executorService);
        /*
        future01.runAfterBothAsync(future02, () -> {
            System.out.println("任务3");
        }, executorService);
         */
        /*
        future01.thenAcceptBothAsync(future02, (x, y) -> {
            System.out.println("x:" + x + ",y:" + y + " 任务3开始");
        }, executorService);
         */
        CompletableFuture<String> future03 = future01.thenCombineAsync(future02, (x, y) -> {
            System.out.println("x:" + x + ",y:" + y + " 任务3开始");
            return x + y;
        }, executorService);
        System.out.println("main...end...result" + future03.get());
    }

    public static class Thread01 extends Thread {
        @Override
        public void run() {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }

    public static class Runnable01 implements Runnable {
        @Override
        public void run() {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
        }
    }

    public static class Callable01 implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }
    }
}
